/**********************************************************************
* Filename: Jogo.java
* Created: 2012/04/30
* @author Fernando Brito e Abreu
**********************************************************************/
package pt.iscteiul.worldfootball.businesslayer;

import java.util.Set;
import java.util.HashSet;
import java.util.SortedSet;
import java.util.TreeSet;

import com.projectpoint.annotationnotfinished.NotFinished;
@NotFinished(value="Not tested")
public class Jogo implements Cloneable
{
	public static Set<Jogo> allInstances = new HashSet<Jogo>();
	
	private CalendarDate dia;
	private String hora;
	private int tempoTotal;
	private Grupo grupo;
	private Estadio estadio;
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Jogo jogo = new Jogo(new CalendarDate(dia.day(),dia.month(), dia.year()),new String(hora), tempoTotal,(Grupo)grupo.clone(),(Estadio)estadio.clone());
		Jogo.allInstances.remove(jogo);
		return super.clone();
	}
	
	protected boolean _Invariant(){
		// let c = self.grupo.campeonato in self.seleccao.forAll(s|s.participado.collect(p|p=c)->size=1)
		boolean jogoPaisPertenceCampeonatoGrupo = true;
		
		{
			Campeonato c = this.grupo().campeonato();
			for(Pais selecao:this.seleccao()){
				HashSet<Campeonato> paisesMatch = new HashSet<Campeonato>();
				for(Campeonato pais:selecao.participado()){
					if(c.equals(pais)){
						paisesMatch.add(pais);
					}
				}
				if(paisesMatch.size()!=1){
					jogoPaisPertenceCampeonatoGrupo =false; 
				}
			}
		}
		return jogoPaisPertenceCampeonatoGrupo;
	}
	
	/**********************************************************************
	* Default constructor
	**********************************************************************/
	public Jogo()
	{
		allInstances.add(this);
	}
	
	/**********************************************************************
	* Parameterized constructor
	* @param dia the dia to initialize
	* @param hora the hora to initialize
	* @param tempoTotal the tempoTotal to initialize
	* @param grupo the grupo to initialize
	* @param estadio the estadio to initialize
	**********************************************************************/
	public Jogo(CalendarDate dia, String hora, int tempoTotal, Grupo grupo, Estadio estadio)
	{
		this.dia = dia;
		this.hora = hora;
		this.tempoTotal = tempoTotal;
		this.grupo = grupo;
		this.estadio = estadio;
		allInstances.add(this);
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the dia of the jogo
	**********************************************************************/
	public CalendarDate dia()
	{
		return dia;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param dia the dia to set
	**********************************************************************/
	public void setDia(CalendarDate dia)
	{
		this.dia = dia;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the hora of the jogo
	**********************************************************************/
	public String hora()
	{
		return hora;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param hora the hora to set
	**********************************************************************/
	public void setHora(String hora)
	{
		this.hora = hora;
	}
	
	/**********************************************************************
	* Standard attribute getter
	* @return the tempoTotal of the jogo
	**********************************************************************/
	public int tempoTotal()
	{
		return tempoTotal;
	}
	
	/**********************************************************************
	* Standard attribute setter
	* @param tempoTotal the tempoTotal to set
	**********************************************************************/
	public void setTempoTotal(int tempoTotal)
	{
		this.tempoTotal = tempoTotal;
	}
	
	/**********************************************************************
	* ONE2MANY getter for Jogo[*] <-> Grupo[1]
	* @return the grupo of the jogo
	**********************************************************************/
	public Grupo grupo()
	{
		return grupo;
	}
	
	/**********************************************************************
	* ONE2MANY setter for Jogo[*] <-> Grupo[1]
	* @param grupo the grupo to set
	**********************************************************************/
	public void setGrupo(Grupo grupo)
	{
		this.grupo = grupo;
	}
	
	/**********************************************************************
	* ONE2MANY getter for Jogo[*] <-> Estadio[1]
	* @return the estadio of the jogo
	**********************************************************************/
	public Estadio estadio()
	{
		return estadio;
	}
	
	/**********************************************************************
	* ONE2MANY setter for Jogo[*] <-> Estadio[1]
	* @param estadio the estadio to set
	**********************************************************************/
	public void setEstadio(Estadio estadio)
	{
		this.estadio = estadio;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE getter for Jogo[*] <-> Equipa[2] ordered
	* @return the equipa of the jogo
	**********************************************************************/
	public SortedSet<Equipa> equipa()
	{
		SortedSet<Equipa> result = new TreeSet<Equipa>();
		for (Equipa x : Equipa.allInstances)
			if (x.jogo()  ==  this)
				result.add(x);
		return result;
	}
	
	/**********************************************************************
	* MEMBER2ASSOCIATIVE setter for Jogo[*] <-> Equipa[2] ordered
	* @param equipa the equipa to set
	**********************************************************************/
	public void setEquipa(SortedSet<Equipa> equipa)
	{
		for (Equipa x : equipa)
			x.setJogo(this);
	}
	
	/**********************************************************************
	* MEMBER2MEMBER getter for Jogo[*] <-> Pais[2] ordered
	* @return the seleccao of the jogo
	**********************************************************************/
	public SortedSet<Pais> seleccao()
	{
		SortedSet<Pais> result = new TreeSet<Pais>();
		for (Equipa x : Equipa.allInstances)
			if (x.jogo()  ==  this)
				result.add(x.seleccao());
		return result;
	}
	
	/**********************************************************************
	* MEMBER2MEMBER setter for Jogo[*] <-> Pais[2] ordered
	* @param seleccao the seleccao to set
	**********************************************************************/
	public void setSeleccao(SortedSet<Pais> seleccao)
	{
		for (Pais t : seleccao)
			for (Equipa x: Equipa.allInstances)
				if (x.jogo() == this)
					x.setSeleccao(t);
	}
	
	/**********************************************************************
	* User-defined operation specified in SOIL/OCL
	* @param data the data to set
	* @param hora the hora to set
	* @param visitado the visitado to set
	* @param visitante the visitante to set
	* @param estadio the estadio to set
	* @param grupo the grupo to set
	* @param tempoTotal the tempoTotal to set
	**********************************************************************/
	public void inicializa(String data, String hora, Pais visitado, Pais visitante, Estadio estadio, Grupo grupo, int tempoTotal)
	{
		//	TODO
		//	dummy := new CalendarDate;
		CalendarDate dummy = new CalendarDate();
		//	 self.dia := dummy.stringToDate(data);
		this.dia = dummy.stringToDate(data);
		//	 destroy dummy;
		CalendarDate.allInstances.remove(dummy);
		//	 self.hora := hora;
		this.hora = hora;
		//	 if visitado.isDefined then new Equipa between (visitado,self) end;
		if(visitado!=null){
			Equipa equipa = new Equipa();
			equipa.setSeleccao(visitado);
			SortedSet<Equipa> visitadoSet =new TreeSet<Equipa>();
			visitadoSet.add(equipa);
			this.setEquipa(visitadoSet);
		}
		//	 if visitante.isDefined then new Equipa between (visitante,self) end;
		if(visitado!=null){
			Equipa equipa = new Equipa();
			equipa.setSeleccao(visitante);
			SortedSet<Equipa> visitanteSet =new TreeSet<Equipa>();
			visitanteSet.add(equipa);
			this.setEquipa(visitanteSet);
		}
		//	 insert (estadio,self) into Estadio_Jogo;
		this.setEstadio(estadio);
		//	 insert (grupo,self) into Grupo_Jogo;
		this.setGrupo(grupo);
		//	 self.tempoTotal := tempoTotal;
		this.setTempoTotal(tempoTotal);
	}
	
	/* (non-Javadoc)
	* @see java.lang.Object#toString()
	*/
	@Override
	/**********************************************************************
	* Object serializer
	**********************************************************************/
	public String toString()
	{
		return "Jogo [dia=" + dia + ", hora=" + hora + ", tempoTotal=" + tempoTotal + ", grupo=" + grupo + ", estadio=" + estadio + "]\n";
	}
	
}
